package com.sobot.finance.poc.web.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.sobot.finance.poc.web.cons.SysConst;
import com.sobot.finance.poc.web.controller.CallbackController;
import com.sobot.finance.poc.web.controller.request.GeneralReq;
import com.sobot.finance.poc.web.entity.CallbackData;
import com.sobot.finance.poc.web.entity.CallbackRecord;
import com.sobot.finance.poc.web.util.ApiClient;
import com.sobot.finance.poc.web.util.PocClient;
import com.sobot.finance.poc.web.util.RedisClient;
import com.sobot.finance.poc.web.util.SmsClient;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author baiyp
 */
@Slf4j
@Service
public class CallbackService {

    @Resource
    private PocClient pocClient;

    @Resource
    private TaskService taskService;

    @Resource
    private SmsClient smsClient;

    @Resource
    private RedisClient redisClient;

    private static final String SYS_ID = "cs";
    private static final String CHANNEL_NO = "ZC";
    private static final String VERSION = "1.0";

    private static final String SMS_TMP = "sms_send_{}_{}_{}";

    @Async
    public ApiClient.ApiRes callback(CallbackController.CallbackResult result) {
        CallbackController.CallbackData data = result.getData();
        CallbackController.CallbackDetail detail = data.getDetail();

        String id = detail.getTaskId();
        String telNo = detail.getTel();

        String batchNo = taskService.getBatchNo(id);

        String sceneCode = taskService.getSceneCode(batchNo);

        String batchName = taskService.getBatchName(batchNo);

        String taskNo = taskService.getTel(batchNo, telNo);

        String callID = detail.getCallID();
        // 单位：微秒
        Long startTime = detail.getStartTime();
        // 单位：微秒
        Long endTime = detail.getEndTime();
        // 通话时⻓ 单位：秒
        Integer feeDuration = detail.getFeeDuration();
        // 呼叫时⻓ 单位：秒
        Integer callDuration = detail.getCallDuration();
        Integer status = detail.getStatus();
        String intentionName = detail.getIntentionName();
        String voiceUrl = detail.getVoiceUrl();
        String outId = detail.getOutId();

        GeneralReq<CallbackData> generalReq = new GeneralReq<>();

        CallbackData callbackData = new CallbackData();
        callbackData.setBatchName(batchName);
        callbackData.setBatchUid(batchNo);
        callbackData.setTelNo(telNo);
        callbackData.setSceneCode(sceneCode);
        callbackData.setTaskUid(taskNo);

        List<CallbackRecord> callbackRecords = Lists.newArrayList();
        CallbackRecord callbackRecord = new CallbackRecord();
        callbackRecord.setCallId(callID);
        callbackRecord.setCallStartTime(startTime / 1000);
        callbackRecord.setCallEndTime(endTime / 1000);
        callbackRecord.setCallTimes(feeDuration * 1000L);
        callbackRecord.setRingTime(callDuration * 1000L);
        callbackRecord.setCallStatus(SysConst.STATUS_MAP.getOrDefault(status, StrUtil.EMPTY));
        callbackRecord.setCustPur(CollUtil.getLast(StrUtil.split(intentionName, StrUtil.C_COMMA)));

        // 获取短信内容
        String msg = taskService.getMsg(batchNo, telNo);
        String key = StrUtil.format(SMS_TMP, id, outId, taskNo);
        boolean exist = redisClient.exist(key);
        if (BooleanUtil.negate(exist)) {
            // 调用发送短信接口
            boolean smsResult = smsClient.sendSms(telNo, msg);
            if (smsResult) {
                callbackRecord.setSmsSendStatus("已发送");
            } else {
                callbackRecord.setSmsSendStatus("未发送");
            }
            redisClient.set(key, telNo);
        } else {
            callbackRecord.setSmsSendStatus(StrUtil.EMPTY);
        }


        callbackRecord.setRecordUrl(voiceUrl);
        callbackRecords.add(callbackRecord);
        callbackData.setCallRecordList(callbackRecords);

        generalReq.setFlowId(IdUtil.objectId());
        generalReq.setSysId(SYS_ID);
        generalReq.setTimestamp(System.currentTimeMillis() + StrUtil.EMPTY);
        generalReq.setChannelNo(CHANNEL_NO);
        generalReq.setVersion(VERSION);
        generalReq.setData(callbackData);

        boolean success = pocClient.callback(generalReq);
        if (!success) {
            log.error("[推送失败]: {}", new Gson().toJson(generalReq));
        }
        return ApiClient.ApiRes.succeed();
    }

    public ApiClient.ApiRes manualCallback(String json) {
        boolean success = pocClient.manualCallback(json);
        if (!success) {
            log.error("[推送失败]: {}", json);
        }
        return ApiClient.ApiRes.succeed();
    }

    public ApiClient.ApiRes sendSms(String batchNo) {
        Gson gson = new Gson();
        String fail = "13103967821,13191601990,13169368801,13103554066,13021062851,13120073933,13271153956,13258083371,13158381757,13355182840,13283786588,13199442865,13192272135,13372810517,13353856166,13381077720,13400703343,13364390228,13522219120,13528402665,13455413354,13419779399,13524982990,13409731933,13554848872,13420548177,13464546225,13562221200,13593352664,13536715565,13598418503,13562891600,13569812718,13569680088,13613719332,13598405970,13598820076,13603139036,13658890108,13623975236,13717967928,13704641222,13639668100,13688839186,13786547831,13696628218,13754246995,13673408500,13695552696";
        Set<String> fails = Sets.newHashSet(StrUtil.split(fail, StrUtil.C_COMMA));
        String fail_ = "18695960186,13991337553,15820702024,18595258955,15153832379,13833930167,18538232829,18638286881,15803720085,15880034217,15776949333,18759477535,18394308175,18559876677,15858227712,13902691050,16605937782,18383925048,18666502650,18974737705,18711021878,17636574345,15640166420,15882631272,18639925557,18567628657,15382343870,15803809585,15160710045,15237222298,15852740302,15956721499,18268423891,18724629384,18621760896,15607080760,18638717717,18272827969,18118322335,18300702772,15936995186,13991329262,15543960231,15997081774,18057292683,15238513851,15282991119,13801109071,18937593275,18508212034,15038220998,15101021786,18300653655,17633004446,15920492654,18047137817,17756309550,13733845054,17679260082,15908319601,18237036650,18238099681,15261299072,15256581711,18660977668,15135088861,18768407371,18054900617,13972050879,15092936555,15759708890,15260505363,18124805999,15250096017,17604779552,18790497872,15055458010,18633062941,15313289998,15802723237,15269091456,18232510264,15939130197,15673058822,15036509056,18286134131,15860307605,15611036315,18909043164,15629101770,18867932722,15021899402,18334772215,15215000626,18838230573,13969088196,15060016950,18457080010,18214955588,15845573897,18313717740,13752686212,13859772707,18661560538,18656153877,13838167682,15131941557,15990208868,17666562490,18511032578,18356504034,15958591908,15751220530,18270669585,18326323050,15042083883,15801777867,18759506588,15738589368,18220591291,15390392196,18300514148,13881472444,15184742757,18737393297,13968999035,18871314302,18128280707,17784497790,18567850973,18627772090,15665230560,15957135185,18540178568,17386057470,18663458879,15136472963,17742549697,15132280634,13838527217,15201630128,18386658490,13901478445,18447073708,13992836723,15114651992,15613585064,17508425198,18287028212,13917312473";
        Set<String> fails_ = Sets.newHashSet(StrUtil.split(fail_, StrUtil.C_COMMA));
        String json = ResourceUtil.readUtf8Str("json/sms.json");
        List<TaskService.UnSend> allSends = gson.fromJson(json, new TypeToken<List<TaskService.UnSend>>() {
        }.getType());
        Set<String> all = allSends.stream().map(TaskService.UnSend::getDn).collect(Collectors.toSet());
        log.info("[all]: {}", gson.toJson(all));
        List<String> successes = Lists.newArrayList();
        for (String tel : all) {
            if (fails.contains(tel)) {
                continue;
            }
            if (fails_.contains(tel)) {
                continue;
            }
            String msg = taskService.getMsg(batchNo, tel);
            boolean b = smsClient.sendSms(tel, msg);
            if (b) {
                successes.add(tel);
            }
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
            }
        }
        log.info("[sends]: {}", gson.toJson(successes));
        return ApiClient.ApiRes.succeed();
    }
}
